﻿using AssetStudio;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Serilog;
using System.ComponentModel.DataAnnotations;
using System.Resources;
using System.Runtime.CompilerServices;

namespace ShaoNv
{
    //每个SubMesh顶点编号baseVertex firstVertex区别
    [MessagePack.MessagePackObject(true)]
    public class SubMesh
    {
        public uint firstByte;
        public uint indexCount;
        //public GfxPrimitiveType topology;
        public uint triangleCount;
        public uint baseVertex;
        public uint firstVertex;
        public uint vertexCount;
        //public AABB localAABB;
    }
    [MessagePack.MessagePackObject(true)]
    public class Mesh
    {
        public string m_Name;
        public List<SubMesh> m_SubMeshes;
        public Matrix4x4[] m_BindPose;
        public uint[] m_BoneNameHashes;
        public int m_VertexCount;
        public float[] m_Vertices;

    }
}

namespace AssetStudioGUI
{
    internal static class Exporter
    {
        public static bool ExportTexture2D(AssetItem item, string exportPath)
        {
            var m_Texture2D = (Texture2D)item.Asset;
            if (Properties.Settings.Default.convertTexture)
            {
                var type = Properties.Settings.Default.convertType;
                if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
                    return false;
                var image = m_Texture2D.ConvertToImage(true);
                if (image == null)
                {
                    Log.Error($"Image Load Fail {m_Texture2D.m_Name}");
                    return false;
                }
                using (image)
                {
                    using (var file = File.OpenWrite(exportFullPath))
                    {
                        image.WriteToStream(file, type);
                    }
                    return true;
                }
            }
            else
            {
                if (!TryExportFile(exportPath, item, ".tex", out var exportFullPath))
                    return false;
                File.WriteAllBytes(exportFullPath, m_Texture2D.image_data.GetData());
                return true;
            }
        }

        public static bool ExportAudioClip(AssetItem item, string exportPath)
        {
            var m_AudioClip = (AudioClip)item.Asset;
            var m_AudioData = m_AudioClip.m_AudioData.GetData();
            if (m_AudioData == null || m_AudioData.Length == 0)
                return false;
            var converter = new AudioClipConverter(m_AudioClip);
            if (Properties.Settings.Default.convertAudio && converter.IsSupport)
            {
                if (!TryExportFile(exportPath, item, ".wav", out var exportFullPath))
                    return false;
                var buffer = converter.ConvertToWav();
                if (buffer == null)
                    return false;
                File.WriteAllBytes(exportFullPath, buffer);
            }
            else
            {
                if (!TryExportFile(exportPath, item, converter.GetExtensionName(), out var exportFullPath))
                    return false;
                File.WriteAllBytes(exportFullPath, m_AudioData);
            }
            return true;
        }

        //通过TypeTree读取数据转化Shader代码
        public static bool ExportShaderMsgPack(AssetItem item, string exportPath)
        {
            if (!TryExportFile(exportPath, item, ".shader", out var exportFullPath))
                return false;
            var m_Shader = (Shader)item.Asset;
            var str = m_Shader.Convert();
            File.WriteAllText(exportFullPath, str);
            return true;
        }
        public static bool ExportShader(AssetItem item, string exportPath)
        {
            if (!TryExportFile(exportPath, item, ".shader", out var exportFullPath))
                return false;
            var m_Shader = (Shader)item.Asset;
            var str = m_Shader.Convert();
            File.WriteAllText(exportFullPath, str);
            return true;
        }

        public static bool ExportTextAsset(AssetItem item, string exportPath)
        {
            var m_TextAsset = (TextAsset)(item.Asset);
            var extension = ".txt";
            if (Properties.Settings.Default.restoreExtensionName)
            {
                if (!string.IsNullOrEmpty(item.Container))
                {
                    extension = Path.GetExtension(item.Container);
                }
            }
            if (!TryExportFile(exportPath, item, extension, out var exportFullPath))
                return false;
            File.WriteAllBytes(exportFullPath, m_TextAsset.m_Script);
            return true;
        }

        public static bool ExportMonoBehaviour(AssetItem item, string exportPath)
        {
            if (!TryExportFile(exportPath, item, ".json", out var exportFullPath))
                return false;
            var m_MonoBehaviour = (MonoBehaviour)item.Asset;
            var type = m_MonoBehaviour.ToType();
            if (type == null)
            {
                var m_Type = Studio.MonoBehaviourToTypeTree(m_MonoBehaviour);
                type = m_MonoBehaviour.ToType(m_Type);
            }
            var str = JsonConvert.SerializeObject(type, Formatting.Indented);
            if(exportFullPath.Length > 250)
            {
                var dir = Path.GetDirectoryName(exportFullPath);
                var fn = Path.GetFileName(exportFullPath);
                exportFullPath = Path.Combine(dir, fn.Substring(0, 10));
            }
            File.WriteAllText(exportFullPath, str);
            return true;
        }

        public static bool ExportFont(AssetItem item, string exportPath)
        {
            var m_Font = (Font)item.Asset;
            if (m_Font.m_FontData != null)
            {
                var extension = ".ttf";
                if (m_Font.m_FontData[0] == 79 && m_Font.m_FontData[1] == 84 && m_Font.m_FontData[2] == 84 && m_Font.m_FontData[3] == 79)
                {
                    extension = ".otf";
                }
                if (!TryExportFile(exportPath, item, extension, out var exportFullPath))
                    return false;
                File.WriteAllBytes(exportFullPath, m_Font.m_FontData);
                return true;
            }
            return false;
        }

        //导出UnityMesh数据
        //搭配slg的Avatar数据
        public static bool ExportUnityMesh(AssetItem item, string exportPath)
        {
            var m_Mesh = (Mesh)item.Asset;
            if (m_Mesh.m_VertexCount <= 0)
                return false;
            //导出MsgPack对象
            if (!TryExportFile(exportPath, item, ".bytes", out var exportFullPath))
                return false;
            var bts = MessagePack.MessagePackSerializer.Serialize(m_Mesh);
            File.WriteAllBytes(exportFullPath, bts);
            //var json = MessagePack.MessagePackSerializer.SerializeToJson(m_Mesh);
            var json = MessagePack.MessagePackSerializer.ConvertToJson(bts);
            var js = Newtonsoft.Json.Linq.JToken.Parse(json);
            var pretty = js.ToString(Formatting.Indented);
            var jsonP = Path.ChangeExtension(exportFullPath, ".json");
            File.WriteAllText(jsonP, pretty);
            return true;
        }
        public static bool ExportMesh(AssetItem item, string exportPath)
        {
            return ExportUnityMesh(item, exportPath);
            var m_Mesh = (Mesh)item.Asset;
            if (m_Mesh.m_VertexCount <= 0)
                return false;
            if (!TryExportFile(exportPath, item, ".obj", out var exportFullPath))
                return false;
            var sb = new StringBuilder();
            sb.AppendLine("g " + m_Mesh.m_Name);
            #region Vertices
            if (m_Mesh.m_Vertices == null || m_Mesh.m_Vertices.Length == 0)
            {
                return false;
            }
            int c = 3;
            if (m_Mesh.m_Vertices.Length == m_Mesh.m_VertexCount * 4)
            {
                c = 4;
            }
            for (int v = 0; v < m_Mesh.m_VertexCount; v++)
            {
                sb.AppendFormat("v {0} {1} {2}\r\n", -m_Mesh.m_Vertices[v * c], m_Mesh.m_Vertices[v * c + 1], m_Mesh.m_Vertices[v * c + 2]);
            }
            #endregion

            #region UV
            if (m_Mesh.m_UV0?.Length > 0)
            {
                c = 4;
                if (m_Mesh.m_UV0.Length == m_Mesh.m_VertexCount * 2)
                {
                    c = 2;
                }
                else if (m_Mesh.m_UV0.Length == m_Mesh.m_VertexCount * 3)
                {
                    c = 3;
                }
                for (int v = 0; v < m_Mesh.m_VertexCount; v++)
                {
                    sb.AppendFormat("vt {0} {1}\r\n", m_Mesh.m_UV0[v * c], m_Mesh.m_UV0[v * c + 1]);
                }
            }
            #endregion

            #region Normals
            if (m_Mesh.m_Normals?.Length > 0)
            {
                if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 3)
                {
                    c = 3;
                }
                else if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 4)
                {
                    c = 4;
                }
                for (int v = 0; v < m_Mesh.m_VertexCount; v++)
                {
                    sb.AppendFormat("vn {0} {1} {2}\r\n", -m_Mesh.m_Normals[v * c], m_Mesh.m_Normals[v * c + 1], m_Mesh.m_Normals[v * c + 2]);
                }
            }
            #endregion

            #region Face
            int sum = 0;
            for (var i = 0; i < m_Mesh.m_SubMeshes.Length; i++)
            {
                sb.AppendLine($"g {m_Mesh.m_Name}_{i}");
                int indexCount = (int)m_Mesh.m_SubMeshes[i].indexCount;
                var end = sum + indexCount / 3;
                for (int f = sum; f < end; f++)
                {
                    sb.AppendFormat("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\r\n", m_Mesh.m_Indices[f * 3 + 2] + 1, m_Mesh.m_Indices[f * 3 + 1] + 1, m_Mesh.m_Indices[f * 3] + 1);
                }
                sum = end;
            }
            #endregion

            sb.Replace("NaN", "0");
            File.WriteAllText(exportFullPath, sb.ToString());
            return true;
        }

        public static bool ExportVideoClip(AssetItem item, string exportPath)
        {
            var m_VideoClip = (VideoClip)item.Asset;
            if (m_VideoClip.m_ExternalResources.m_Size > 0)
            {
                if (!TryExportFile(exportPath, item, Path.GetExtension(m_VideoClip.m_OriginalPath), out var exportFullPath))
                    return false;
                m_VideoClip.m_VideoData.WriteData(exportFullPath);
                return true;
            }
            return false;
        }

        public static bool ExportMovieTexture(AssetItem item, string exportPath)
        {
            var m_MovieTexture = (MovieTexture)item.Asset;
            if (!TryExportFile(exportPath, item, ".ogv", out var exportFullPath))
                return false;
            File.WriteAllBytes(exportFullPath, m_MovieTexture.m_MovieData);
            return true;
        }

        public static bool ExportSprite(AssetItem item, string exportPath)
        {
            var type = Properties.Settings.Default.convertType;
            if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
                return false;
            var image = ((Sprite)item.Asset).GetImage();
            if (image != null)
            {
                using (image)
                {
                    using (var file = File.OpenWrite(exportFullPath))
                    {
                        image.WriteToStream(file, type);
                    }
                    return true;
                }
            }
            return false;
        }

        public static bool ExportRawFile(AssetItem item, string exportPath)
        {
            if (!TryExportFile(exportPath, item, ".dat", out var exportFullPath))
                return false;
            File.WriteAllBytes(exportFullPath, item.Asset.GetRawData());
            return true;
        }

        private static bool TryExportFile(string dir, AssetItem item, string extension, out string fullPath)
        {
            var fileName = FixFileName(item.Text);
            fullPath = Path.Combine(dir, fileName + extension);
            if (!File.Exists(fullPath))
            {
                Directory.CreateDirectory(dir);
                return true;
            }
            fullPath = Path.Combine(dir, fileName + item.UniqueID + extension);
            if (!File.Exists(fullPath))
            {
                Directory.CreateDirectory(dir);
                return true;
            }
            return false;
        }
        //动画是SMD格式二进制文件
        public static bool ExportAniClip(AssetItem item, string exportPath)
        {
            var exportFullPath = Path.Combine(exportPath, item.Text + ".bytes");
            if (File.Exists(exportFullPath))
            {
                exportFullPath = Path.Combine(exportPath, item.Text + item.UniqueID+".bytes");
            }
            Animator ani = null;
            var convert = new ModelConverter(new AnimationClip[] { (AnimationClip)item.Asset });
            Log.Information($"ExportAniClip {convert}");
            ExportSMD(convert, exportFullPath);
            return true;
        }
        //导出MsgPack数据
        public static bool ExportTerrainData(AssetItem item, string exportPath)
        {
            var exportFullPath = Path.Combine(exportPath, item.Text + ".bytes");
            if (File.Exists(exportFullPath))
            {
                exportFullPath = Path.Combine(exportPath, item.Text + item.UniqueID + ".bytes");
            }
            var bt = MessagePack.MessagePackSerializer.Serialize(item.Asset as TerrainData);
            var dir = Path.GetDirectoryName(exportFullPath);
            if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
            File.WriteAllBytes(exportFullPath, bt);
            return true;
        }

        //导出Animator时候可以选择动画
        //现在只单独导出动画不要Animator了 Path导出为数字在Unity中还原 找不到对应的Avatar
        //导出动画和骨架
        public static bool ExportAnimator(AssetItem item, string exportPath, List<AssetItem> animationList = null)
        {
            var exportFullPath = Path.Combine(exportPath, item.Text, item.Text + ".fbx");
            if (File.Exists(exportFullPath))
            {
                exportFullPath = Path.Combine(exportPath, item.Text + item.UniqueID, item.Text + ".fbx");
            }
            var m_Animator = (Animator)item.Asset;
            Console.WriteLine($"ExportAnimator {item} {exportPath} {animationList}");
            var convert = animationList != null
                ? new ModelConverter(m_Animator, Properties.Settings.Default.convertType, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
                : new ModelConverter(m_Animator, Properties.Settings.Default.convertType);
            //动画曲线没有到处完整 只导出了部分曲线
            Console.WriteLine($"ExportFBX");
            //之前骨架选择错误了 应该用 _slg_skinAvatar.txt 骨架 但是mesh要怎么绑定
            //导出基础骨架模型
            //ExportFbx(convert, exportFullPath);
            //导出每个动画文件
            ExportSMD(convert, exportFullPath);
            return true;
        }

        public static void ExportGameObject(GameObject gameObject, string exportPath, List<AssetItem> animationList = null)
        {
            var convert = animationList != null
                ? new ModelConverter(gameObject, Properties.Settings.Default.convertType, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
                : new ModelConverter(gameObject, Properties.Settings.Default.convertType);
            exportPath = exportPath + FixFileName(gameObject.m_Name) + ".fbx";
            ExportFbx(convert, exportPath);
        }

        public static void ExportGameObjectMerge(List<GameObject> gameObject, string exportPath, List<AssetItem> animationList = null)
        {
            var rootName = Path.GetFileNameWithoutExtension(exportPath);
            var convert = animationList != null
                ? new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
                : new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType);
            ExportFbx(convert, exportPath);
        }
        [MessagePack.MessagePackObject(false)]
        public class KeyFrame
        {
            [MessagePack.Key(0)]
            public float time;
            [MessagePack.Key(1)]
            public Vector4 value;
        }
        [MessagePack.MessagePackObject(false)]
        public class Track
        {
            [MessagePack.Key(0)]
            public string path;
            [MessagePack.Key(1)]
            public List<KeyFrame> pos = new List<KeyFrame>();
            [MessagePack.Key(2)]
            public List<KeyFrame> rot = new List<KeyFrame>();
            [MessagePack.Key(3)]
            public List<KeyFrame> scale = new List<KeyFrame>();
            [MessagePack.Key(4)]
            public List<KeyFrame> rotQua = new List<KeyFrame>();
            [MessagePack.Key(5)]
            public List<KeyFrame> rootCurve = new List<KeyFrame>();
        }
        [MessagePack.MessagePackObject(false)]
        public class SmdFile
        {
            [MessagePack.Key(0)]
            public List<Track> track = new List<Track>();
            [MessagePack.Key(1)]
            public float sampleRate = 60;
        }
        //BoneInfo + AnimationInfo Time
        private static void ExportSMD(IImported convert, string exportPath)
        {
            var bone = convert.RootFrame;
            var aniList = convert.AnimationList;
            Console.WriteLine($"ExportSMD {convert} {exportPath} {aniList} {aniList.Count}");
            var dir = Path.GetDirectoryName(exportPath);
            if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
            foreach(var ani in aniList)
            {
                var oneAni = new SmdFile();
                oneAni.sampleRate = ani.SampleRate;
                var sb = new StringBuilder();
                sb.AppendLine($"TrackCount {ani.TrackList.Count}");
                oneAni.track = new List<Track>();
                //每个track 有对应的time CurveValue
                //导入到Unity里面重新组装Curve
                //位置 旋转 缩放 轴方向保持原样
                foreach(var t in ani.TrackList)
                {
                    var track = new Track();
                    oneAni.track.Add(track);
                    track.path = t.Path;
                    sb.AppendLine($"path {t.Path} {t.TranslationsO.Count} {t.RotationsE.Count} {t.RotationsO.Count} {t.ScalingsO.Count}");
                    sb.AppendLine($"pos");
                    foreach(var p in t.TranslationsO)
                    {
                        sb.AppendLine($"{p.time} {p.value}");
                        track.pos.Add(new KeyFrame() { time = p.time, value = p.value});
                    }
                    sb.AppendLine($"rot");
                    foreach(var p in t.RotationsE)
                    {
                        sb.AppendLine($"{p.time} {p.value}");
                        track.rot.Add(new KeyFrame() { time = p.time, value = p.value});
                    }
                    sb.AppendLine($"rotO");
                    foreach(var p in t.RotationsO)
                    {
                        sb.AppendLine($"{p.time} {p.value}");
                        track.rotQua.Add(new KeyFrame() { time = p.time, value = new Vector4(p.value.X, p.value.Y, p.value.Z, p.value.W) });
                    }
                    sb.AppendLine($"scale");
                    foreach(var p in t.ScalingsO)
                    {
                        sb.AppendLine($"{p.time} {p.value}");
                        track.scale.Add(new KeyFrame() { time = p.time, value = p.value});
                    }
                    sb.AppendLine($"rootCurve");
                    foreach(var p in t.rootCurve)
                    {
                        sb.AppendLine($"{p.time}, {p.value}");
                        track.rootCurve.Add(new KeyFrame() { time = p.time, value = new Vector4(p.value, 0, 0, 0)});
                    }
                }
                var aniFile = Path.Combine(dir, ani.Name + ".bytes");
                var bt = MessagePack.MessagePackSerializer.Serialize(oneAni);
                File.WriteAllBytes(aniFile, bt);
                var sbOut = Path.Combine(dir, ani.Name + ".txt");
                File.WriteAllText(sbOut, sb.ToString());
                //var json = MessagePack.MessagePackSerializer.ConvertToJson(bt);
                //var jp = Newtonsoft.Json.Linq.JToken.Parse(json);
                //var intt = jp.ToString( Formatting.Indented );
                //File.WriteAllText(intt, Path.Combine(dir, ani.Name+".json"));
            }
        }
        private static void ExportFbx(IImported convert, string exportPath)
        {
            var eulerFilter = Properties.Settings.Default.eulerFilter;
            var filterPrecision = (float)Properties.Settings.Default.filterPrecision;
            var exportAllNodes = Properties.Settings.Default.exportAllNodes;
            var exportSkins = Properties.Settings.Default.exportSkins;
            var exportAnimations = Properties.Settings.Default.exportAnimations;
            var exportBlendShape = Properties.Settings.Default.exportBlendShape;
            var castToBone = Properties.Settings.Default.castToBone;
            var boneSize = (int)Properties.Settings.Default.boneSize;
            var exportAllUvsAsDiffuseMaps = Properties.Settings.Default.exportAllUvsAsDiffuseMaps;
            var scaleFactor = (float)Properties.Settings.Default.scaleFactor;
            var fbxVersion = Properties.Settings.Default.fbxVersion;
            var fbxFormat = Properties.Settings.Default.fbxFormat;
            ModelExporter.ExportFbx(exportPath, convert, eulerFilter, filterPrecision,
                exportAllNodes, exportSkins, exportAnimations, exportBlendShape, castToBone, boneSize, exportAllUvsAsDiffuseMaps, scaleFactor, fbxVersion, fbxFormat == 1);
        }

        public static bool ExportDumpFile(AssetItem item, string exportPath, ExportType type = ExportType.Dump)
        {
            if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath))
                return false;
            //字体不能导出Dump文件
            if(item.Asset.type == ClassIDType.Font)
            {
                return false;
            }
            //if(item.Asset.type == ClassIDType.SkinnedMeshRenderer)
            //{
            //    var smr = item.Asset as SkinnedMeshRenderer;

            //    return true;
            //}
            string str = null;
            type = ExportType.MsgPack;//强制导出Transform的Pack
            //if (simple)
            if (type == ExportType.Simple)
            {
                str = "";
            }
            else if (type == ExportType.MsgPack)
            {
                byte[] bt;
                //内部包含PathID信息
                //if (item.Asset.type == ClassIDType.Transform) bt = MessagePack.MessagePackSerializer.Serialize(item.Asset as Transform);
                //else if (item.Asset.type == ClassIDType.GameObject) bt = MessagePack.MessagePackSerializer.Serialize(item.Asset as GameObject);

                //else if(item.Asset.type == ClassIDType.ParticleSystemRenderer)
                //else if (item.Asset.type == ClassIDType.MeshFilter) bt = MessagePack.MessagePackSerializer.Serialize(item.Asset as MeshFilter);
                //else if (item.Asset.type == ClassIDType.MeshRenderer) bt = MessagePack.MessagePackSerializer.Serialize(item.Asset as MeshRenderer);
                //else if (item.Asset.type == ClassIDType.BoxCollider) bt = MessagePack.MessagePackSerializer.Serialize(item.Asset as BoxCollider);
                //都导出PathId用于分析
                //else if(item.Asset.type == ClassIDType.ParticleSystem)//导出粒子系统msgPack数据用于Unity加载分析
                //{
                //    bt = null;
                //    //二进制结构数据 便于Unity解析来还原粒子系统
                //    bt = item.Asset.DumpMsgPack(); 
                //}
                //else if (true) //全导出MsgPack 加载读取数据
                //{
                //    bt = null;
                //    bt = item.Asset.DumpMsgPack();
                //}
                //都导出两份一份MsgPack 加载 一份 txt 阅读分析
                //else //其它无法MsgPack就只Dump即可
                {
                    bt = item.Asset.DumpMsgPack();//Dump TypeTree结构
                    //bt = null;
                    //bt = MessagePack.MessagePackSerializer.Serialize(item.Asset);
                    str = item.Asset.Dump();
                    if (str == null && item.Asset is MonoBehaviour m_MonoBehaviour)
                    {
                        var m_Type = Studio.MonoBehaviourToTypeTree(m_MonoBehaviour);
                        str = m_MonoBehaviour.Dump(m_Type);
                    }
                    if (str != null)
                    {
                        var dir2 = Path.GetDirectoryName(exportFullPath);
                        var fn2 = Path.GetFileName(exportFullPath);
                        if (exportFullPath.Length > 250)
                        {
                            exportFullPath = Path.Combine(dir2, fn2.Substring(0, 10));
                        }
                        //导出文件的PathID信息
                        var sb = new StringBuilder();
                        sb.AppendLine($"sourcePath {item.Asset.m_PathID}");
                        sb.AppendLine($"fileName {item.Asset.assetsFile.fileName}");
                        sb.Append(str);
                        File.WriteAllText(exportFullPath, sb.ToString());
                        if(bt != null)
                        {
                            var btsPath = Path.ChangeExtension(exportFullPath, ".bytes");
                            File.WriteAllBytes(btsPath, bt);
                        }
                        return true;
                    }
                    else return false;
                }
                var dir = Path.GetDirectoryName(exportFullPath);
                var fn = Path.GetFileName(exportFullPath);
                if (exportFullPath.Length > 250)
                {
                    exportFullPath = Path.Combine(dir, fn.Substring(0, 10));
                }
                File.WriteAllBytes(exportFullPath, bt);
                return true;
            }
            else
            {
                str = item.Asset.Dump();
                if (str == null && item.Asset is MonoBehaviour m_MonoBehaviour)
                {
                    var m_Type = Studio.MonoBehaviourToTypeTree(m_MonoBehaviour);
                    str = m_MonoBehaviour.Dump(m_Type);
                }
            }
            if (str != null)
            {
                var dir = Path.GetDirectoryName(exportFullPath);
                var fn = Path.GetFileName(exportFullPath);
                if(exportFullPath.Length > 250)
                {
                    exportFullPath = Path.Combine(dir, fn.Substring(0, 10));
                }
                //导出文件的PathID信息
                var sb = new StringBuilder();
                sb.AppendLine($"sourcePath {item.Asset.m_PathID}");
                sb.Append(str);
                File.WriteAllText(exportFullPath, sb.ToString());
                return true;
            }
            return false;
        }

        public static bool ExportConvertFile(AssetItem item, string exportPath)
        {
            switch (item.Type)
            {
                case ClassIDType.Texture2D:
                    return ExportTexture2D(item, exportPath);
                case ClassIDType.AudioClip:
                    return ExportAudioClip(item, exportPath);
                case ClassIDType.Shader:
                    return ExportShader(item, exportPath);
                case ClassIDType.TextAsset:
                    return ExportTextAsset(item, exportPath);
                case ClassIDType.MonoBehaviour:
                    return ExportMonoBehaviour(item, exportPath);
                case ClassIDType.Font:
                    return ExportFont(item, exportPath);
                case ClassIDType.Mesh:
                    return ExportMesh(item, exportPath);
                case ClassIDType.VideoClip:
                    return ExportVideoClip(item, exportPath);
                case ClassIDType.MovieTexture:
                    return ExportMovieTexture(item, exportPath);
                case ClassIDType.Sprite:
                    return ExportSprite(item, exportPath);
                case ClassIDType.Animator:
                    return ExportAnimator(item, exportPath);
                case ClassIDType.AnimationClip:
                    //return false;
                    return ExportAniClip(item, exportPath);//类似导出Animator但是没有骨骼架构只有Track结构
                case ClassIDType.TerrainData:
                    return ExportTerrainData(item, exportPath);
                default:
                    return ExportRawFile(item, exportPath);
            }
        }

        public static string FixFileName(string str)
        {
            if (str.Length >= 260) return Path.GetRandomFileName();
            return Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_'));
        }
    }
}
